package com.topisv.tms.rest.qimen.qmservice;

import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXB;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.EdiGoodsSku;
import com.topisv.tms.entity.LogosticsInfo;
import com.topisv.tms.entity.stock.instorage.InstorageCountItem;
import com.topisv.tms.entity.stock.instorage.pre.InstorageBillItemPre;
import com.topisv.tms.entity.stock.instorage.pre.InstorageBillPre;
import com.topisv.tms.entity.stock.instorage.pre.PreInBill;
import com.topisv.tms.exception.ErrorCode;
import com.topisv.tms.exception.PaiUException;
import com.topisv.tms.repository.EdiGoodsSkuDao;
import com.topisv.tms.repository.LogosticsInfoDao;
import com.topisv.tms.repository.stock.instorage.InstorageCountItemDao;
import com.topisv.tms.repository.stock.preInstorage.InstorageBillItemPreDao;
import com.topisv.tms.repository.stock.preInstorage.InstorageBillPreDao;
import com.topisv.tms.repository.stock.preInstorage.PreInBillDao;
import com.topisv.tms.rest.qimen.qmentity.SenderInfo;
import com.topisv.tms.rest.qimen.qmentity.request.EntryOrderConfirm.EntryOrderConfirm;
import com.topisv.tms.rest.qimen.qmentity.request.EntryOrderConfirm.EntryOrderItemConfirm;
import com.topisv.tms.rest.qimen.qmentity.request.EntryOrderConfirm.InstorageBillCreateConfirm;
import com.topisv.tms.rest.qimen.qmentity.request.ReturnOrderConfirm.ReturnOrderConfirm;
import com.topisv.tms.rest.qimen.qmentity.request.ReturnOrderConfirm.ReturnOrderCreateConfirm;
import com.topisv.tms.rest.qimen.qmentity.request.ReturnOrderConfirm.ReturnOrderItemConfirm;
import com.topisv.tms.rest.qimen.qmenum.InventoryType;
import com.topisv.tms.rest.qimen.qmsend.QmRequestSender;
import com.topisv.tms.rest.qimen.request.RequestMethodType;
import com.topisv.tms.rest.qimen.request.RequestParams;
import com.topisv.tms.service.stock.instorageNew.InstorageScanService;
import com.topisv.tms.utils.InitProperties;
import com.topisv.tms.utils.rule.TMSTransportRule;

@Component
@Transactional(readOnly=true)
@Lazy(false)
public class EntryOrderConfirmService extends QmRequestSender<Map<Object, Object>>{

	private static final Logger logger = LoggerFactory.getLogger(EntryOrderConfirmService.class);
	
	@Autowired
	private InstorageBillPreDao instorageBillPreDao;
	@Autowired
	private InstorageBillItemPreDao instorageBillItemPreDao;
	@Autowired
	private LogosticsInfoDao logosticsInfoDao;
	@Autowired
	private PreInBillDao preInBillDao;
	@Autowired
	private InstorageCountItemDao instorageCountItemDao;
	@Autowired
	private EdiGoodsSkuDao ediGoodsSkuDao;
	@Autowired
	private InstorageScanService instorageScanService;
	@Override
	public RequestParams setupParam(RequestParams sendParams) {
		Map<String,String> params = new HashMap<String,String>();
		params.put("method", RequestMethodType.ENTRYORDER_CONFIRM.getType());
		params.put("format", InitProperties.get("qm.format"));
		params.put("app_key", InitProperties.get("regAppKey"));
		params.put("v", InitProperties.get("qm.v"));
		params.put("sign_method", InitProperties.get("qm.sign_method"));
		params.put("customerId", "");//暂未定
		sendParams.setSecret(InitProperties.get("regAppSecret"));
		sendParams.setParams(params);
		return sendParams;
	}

	@Override
	public String execute(Map<Object, Object> params,RequestParams sendParams) {
		String billType = (String) params.get("billType");
		String status = (String) params.get("status");
		//根据预约单号查出预约单
		String billCode = (String) params.get("preCode");
		InstorageBillPre billPre = instorageBillPreDao.findByBillCode(billCode);
		List<InstorageBillItemPre> billItemPres = instorageBillItemPreDao.query(billPre.getId());
		
		
		sendParams.getParams().put("customerId", billPre.getCustomerCode());
		
		
		if("returnOrder".equals(billType)){
			logger.info("退货入库确认");
			sendParams.getParams().put("method", RequestMethodType.RETURNORDER_CONFIRM.getType());
			ReturnOrderCreateConfirm orderCreateConfirm = new ReturnOrderCreateConfirm();
			ReturnOrderConfirm order = new ReturnOrderConfirm();
			SenderInfo sender = new SenderInfo();
			
			//设置ReturnOrderConfirm数据
			order.setReturnOrderCode(billPre.getCustomerOrderNo());
			order.setReturnOrderId(billPre.getBillCode());
			order.setWarehouseCode(billPre.getInwarehouseCode());
			order.setOrderType("THRK");
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			order.setOrderConfirmTime(sdf.format(new Date()));
			order.setReturnReason(billPre.getReturnReason());
			order.setLogisticsCode(billPre.getLogisticsCode());
			order.setLogisticsName(billPre.getLogisticsName());
			order.setExpressCode(billPre.getExpressNo());
			order.setRemark(billPre.getRemark());
			/*
			 *外部业务编码, 消息ID, 用于去重  by caomingwu
			 */
			order.setOutBizCode(TMSTransportRule.generateByPreFix("QM"));
			
			//查出发件人信息 并设置SenderInfo数据
			LogosticsInfo logosticsInfo = logosticsInfoDao.findByExpressNoAndLogosticsInfo(billPre.getExpressNo(),billPre.getBillCode(),billPre.getLogisticsCode());
			if(logosticsInfo!=null){
				sender.setCompany(logosticsInfo.getSenderCompany());
				sender.setName(logosticsInfo.getSenderName());
				sender.setZipCode(logosticsInfo.getSenderZipCode());
				sender.setTel(logosticsInfo.getSenderTel());
				sender.setMobile(logosticsInfo.getSenderMobile());
				sender.setEmail(logosticsInfo.getSenderEmail());
				sender.setCountryCode(logosticsInfo.getSenderCountryCode());
				sender.setProvince(logosticsInfo.getSenderProvince());
				sender.setCity(logosticsInfo.getSenderCity());
				sender.setArea(logosticsInfo.getSenderArea());
				sender.setTown(logosticsInfo.getSenderTown());
				sender.setDetailAddress(logosticsInfo.getSenderDetailAddress());
			}
			//设置Item数据
			List<ReturnOrderItemConfirm> itemConfirms = new ArrayList<ReturnOrderItemConfirm>();
			
			PreInBill preinbill = preInBillDao.findByPreBillId(billPre.getId());
			
			//
			Map<String, Integer> tmpMap = new HashMap<String, Integer>();
			for (InstorageBillItemPre itemPre : billItemPres) {
				EdiGoodsSku goodsSku = ediGoodsSkuDao.findByCustomerCodeAndSku(billPre.getCustomerCode(), itemPre.getSkuCode());
				if (goodsSku == null) {
					throw new PaiUException(ErrorCode.SKU_CONFIG_ERROR, new String[] { itemPre.getSkuCode() });
				}
				String key = itemPre.getItemId() + "_" + (itemPre.getBatchCode() == null ? "" : itemPre.getBatchCode()) + "_" +
				    (itemPre.getProductDate() == null ? "" : itemPre.getProductDate()) + "_" + 
				    (itemPre.getExpireDate() == null ? "" : itemPre.getExpireDate());
				if(tmpMap.containsKey(key)){
				    tmpMap.put(key, (Integer)tmpMap.get(key) + itemPre.getGoodsNum());
				    continue;
				}else{
				    tmpMap.put(key, itemPre.getGoodsNum());
				}
				
				List<InstorageCountItem> countItem = instorageCountItemDao.loadByBillCode(preinbill.getInBillCode());
				int errorCnt = 0;//破损件数量
				int noterrorCnt = 0;//完整件数量
				if(countItem.size() != 0){
					for(InstorageCountItem count : countItem){
					    /*if(!itemPre.getSkuCode().equals(count.getSku())){
					        continue;
					    }*/
					    if(!(itemPre.getSkuCode().equals(count.getSku())) || 
					       !((itemPre.getBatchCode() == null ? "" : itemPre.getBatchCode()).equals(
					           (count.getBatchCode() == null ? "" : count.getBatchCode()))) || 
					       !((itemPre.getProductDate() == null ? "" : itemPre.getProductDate()).equals(
					           (count.getProductDate() == null ? "" : count.getProductDate()))) ||
					       !((itemPre.getExpireDate() == null ? "" : itemPre.getExpireDate()).equals(
	                            (count.getExpireDate() == null ? "" : count.getExpireDate())))
					      ){
					        continue;
					    }
					    
					    if(InventoryType.ERROR.getType().equals(count.getErrorFlag())){
					        errorCnt += count.getNum();
					    }else{
					        noterrorCnt += count.getNum();
					    }
					}
				}
				if(errorCnt > 0){
				    ReturnOrderItemConfirm error = new ReturnOrderItemConfirm();
				    try {
                        BeanUtils.copyProperties(error, itemPre);
                    } catch (Exception e) {
                    }
				    error.setStockType(InventoryType.getOrderTypeDesc(InventoryType.ERROR.getType()));
				    error.setActualQty(errorCnt);
				    error.setItemCode(goodsSku.getBar());
				    error.setBatchCode(itemPre.getBatchCode());
				    error.setProductDate(itemPre.getProductDate());
				    error.setExpireDate(itemPre.getExpireDate());
				    error.setItemId(goodsSku.getId().toString());
				    error.setOrderLineNo(itemPre.getLineNo());
				    itemConfirms.add(error);
				}
				
				if(noterrorCnt > 0){
				    ReturnOrderItemConfirm noterror = new ReturnOrderItemConfirm();
				    try {
                        BeanUtils.copyProperties(noterror, itemPre);
                    } catch (Exception e) {
                    }
				    noterror.setStockType(InventoryType.getOrderTypeDesc(InventoryType.NOT_ERROR.getType()));
				    noterror.setActualQty(noterrorCnt);
				    noterror.setItemCode(goodsSku.getBar());
				    noterror.setBatchCode(itemPre.getBatchCode());
				    noterror.setProductDate(itemPre.getProductDate());
				    noterror.setExpireDate(itemPre.getExpireDate());
				    noterror.setItemId(goodsSku.getId().toString());
				    noterror.setOrderLineNo(itemPre.getLineNo());
                    itemConfirms.add(noterror);
				}
			}
			
			if(itemConfirms.size() > 0){
                for(ReturnOrderItemConfirm returnOrder : itemConfirms){
                    returnOrder.setQuantity(tmpMap.get(returnOrder.getItemId() + "_" + 
                        (returnOrder.getBatchCode() == null ? "" : returnOrder.getBatchCode()) + "_" +
                        (returnOrder.getProductDate() == null ? "" : returnOrder.getProductDate()) + "_" + 
                        (returnOrder.getExpireDate() == null ? "" : returnOrder.getExpireDate())));//设置计划收货数量
                }
            }
			//把ReturnOrderConfirm和ReturnOrderItemConfirm和SenderInfo放到InstorageBillCreateConfirm
			order.setSenderInfo(sender);
			orderCreateConfirm.setReturnOrder(order);
			orderCreateConfirm.setItem(itemConfirms);
			
			//转成XML返回
			StringWriter writer = new StringWriter();
			JAXB.marshal(orderCreateConfirm,writer);
			logger.info("退货入库确认成功"+writer.toString());
			return writer.toString();
		}else{
			logger.info("普通入库确认");
			InstorageBillCreateConfirm createConfirm = new InstorageBillCreateConfirm();
			EntryOrderConfirm entryOrder = new EntryOrderConfirm();
			//设置EntryOrderConfirm的数据
			entryOrder.setEntryOrderCode(billPre.getCustomerOrderNo());
			entryOrder.setOwnerCode(billPre.getCustomerCode());
			entryOrder.setWarehouseCode(billPre.getInwarehouseCode());
			entryOrder.setEntryOrderId(billPre.getBillCode());
			String type = "";
			if("customer".equals(billType)){
				type = "CGRK";
			}
			else if("allot".equals(billType)){
				type = "DBRK";
			}
			else if("returnOrder".equals(billType)){
				type = "THRK";
			}
			else if("preOrder".equals(billType)){
				type = "CGRK";
			}
			else if("other".equals(billType)){
				type = "QTRK";
			}
			entryOrder.setEntryOrderType(type);
			/**
			 * 返回ERP传进来的预约入库单类型
			 */
			if(StringUtils.isNotBlank(billPre.getBillType())){
				entryOrder.setEntryOrderType(billPre.getBillType());
			}
			entryOrder.setOutBizCode(TMSTransportRule.generateByPreFix("QM"));
			int confirmType = 0;
//			int confirmType = 1;
//			if("2".equals(billPre.getOrderStatus())){
//				confirmType = 0;
//			}
			entryOrder.setConfirmType(confirmType);
			//入库单状态, string (50) , 必填 (NEW-未开始处理, ACCEPT-仓库接单 , 
			//PARTFULFILLED-部分收货完成, FULFILLED-收货完成, EXCEPTION-异常, CANCELED-取消, 
			//CLOSED-关闭, REJECT-拒单, CANCELEDFAIL-取消失败) , (只传英文编码)
			//入库状态 （0:待登记 (调拨货品已出库，尚未入库) 1.入库登记 2.领取点收任务 3.点收完成 4.领取上架任务 5.上架完成 ）
			Map<String,Map<String,Integer>> skuPre = new HashMap<String,Map<String,Integer>>();
			if(!("-1".equals(status))){
				if("0".equals(status))
				{
					entryOrder.setStatus("NEW");
				}
				else if("1".equals(status))
				{
					entryOrder.setStatus("ACCEPT");
				}
				else if("2".equals(status))
				{
					entryOrder.setStatus("INPROCESS");
				}
				else if("3".equals(status))
				{
					entryOrder.setStatus("INPROCESS");
				}
				else if("4".equals(status))
				{
					entryOrder.setStatus("INPROCESS");
				}
				else if("5".equals(status))
				{
					entryOrder.setStatus("FULFILLED");
				}
				entryOrder.setRemark(billPre.getRemark());
				
				PreInBill preinbill = preInBillDao.findByPreBillId(billPre.getId());
				List<InstorageCountItem> countItems = instorageCountItemDao.loadByBillCode(preinbill.getInBillCode());
				if(countItems.size() != 0){
					for(InstorageCountItem count : countItems){
						String errorFlag = count.getErrorFlag();
						if("noterror".equals(errorFlag)){
							errorFlag = "ZP";
						}else{
							errorFlag = "CC";
						}
						String sku = count.getSku();
						String batchCode = count.getBatchCode() == null ? "" : count.getBatchCode();
						String productDate = count.getProductDate() == null ? "" : count.getProductDate();
						String expireDate = count.getExpireDate() == null ? "" : count.getExpireDate();
						String key = sku + "_" + batchCode + "_" + productDate + "_" + expireDate;
						Map<String,Integer> spm = new HashMap<String,Integer>();
						if(!skuPre.containsKey(key)){
							skuPre.put(key,spm);
						}else {
							spm = skuPre.get(key);
						}
						spm.put(errorFlag, ((skuPre.get(key).get(errorFlag)==null?0:skuPre.get(key).get(errorFlag))+count.getNum()));
						skuPre.put(key, spm);
					}
				}
			}else{
				//入库单状态, string (50) , 必填 (NEW-未开始处理, ACCEPT-仓库接单 , 
				//PARTFULFILLED-部分收货完成, FULFILLED-收货完成, EXCEPTION-异常, CANCELED-取消, 
				//CLOSED-关闭, REJECT-拒单, CANCELEDFAIL-取消失败) , (只传英文编码)
				//入库状态 （0：新建 1:部分收货未上架  2:部分收货部分上架 3:部分收货完全上架 4:完全收货未上架 5:完全收货部分上架 6:完全收货完全上架 ）
				logger.info("边收边上架");
				String newStatus=String.valueOf(params.get("newstatus"));
				if("0".equals(newStatus))
				{
					entryOrder.setStatus("NEW");
				}
				else if("3".equals(newStatus))
				{
					entryOrder.setStatus("PARTFULFILLED");
				}
				else if("6".equals(newStatus))
				{
					entryOrder.setStatus("FULFILLED");
				}
				entryOrder.setRemark(billPre.getRemark());
				
				PreInBill preinbill = preInBillDao.findByPreBillId(billPre.getId());
				List<Map<String, Object>> receiptDetailList=this.instorageScanService.getReceiptDetailSKUByBillCodeNew(preinbill.getInBillCode());
				if(receiptDetailList.size() != 0){
					for(int i=0;i<receiptDetailList.size();i++){
						Map<String, Object> map=receiptDetailList.get(i);
						String errorFlag = String.valueOf(map.get("errorFlag"));
						if("noterror".equals(errorFlag)){
							errorFlag = "ZP";
						}else{
							errorFlag = "CC";
						}
						String sku = String.valueOf(map.get("sku"));
//						String batchCode = String.valueOf(map.get("batchCode")) == null ? "" : String.valueOf(map.get("batchCode"));
//						String productDate = String.valueOf(map.get("productDate")) == null ? "" : String.valueOf(map.get("productDate"));
//						String expireDate = String.valueOf(map.get("expireDate")) == null ? "" : String.valueOf(map.get("expireDate"));
						//update by LiBin 20161012 bug564
                        String batchCode =map.get("batchCode") == null ? "" : (String)map.get("batchCode");
                        String productDate =map.get("productDate") == null ? "" : (String)map.get("productDate");
                        String expireDate = map.get("expireDate") == null ? "" : (String)map.get("expireDate");
						String key = sku + "_" + batchCode + "_" + productDate + "_" + expireDate;
						
						Map<String,Integer> spm = new HashMap<String,Integer>();
						if(!skuPre.containsKey(key)){
							skuPre.put(key,spm);
						}else {
							spm = skuPre.get(key);
						}
						spm.put(errorFlag, ((skuPre.get(key).get(errorFlag)==null?0:skuPre.get(key).get(errorFlag))+Integer.valueOf(String.valueOf(map.get("countNum")))));
						skuPre.put(key, spm);
					}
				}
			}
			//设置EntryOrderItemConfirm的数据
			List<EntryOrderItemConfirm> entryOrderItems = new ArrayList<EntryOrderItemConfirm>();
			for (InstorageBillItemPre itemPre : billItemPres) {
				EdiGoodsSku goodsSku = ediGoodsSkuDao.findByCustomerCodeAndSku(billPre.getCustomerCode(), itemPre.getSkuCode());
				if (goodsSku == null) {
					throw new PaiUException(ErrorCode.SKU_CONFIG_ERROR, new String[] { itemPre.getSkuCode() });
				}
				String inventoryType = itemPre.getInventoryType();
				if(!"ZP".equals(inventoryType)){
					inventoryType = "CC";
				}
				for (Map.Entry<String,Map<String,Integer>> entry : skuPre.entrySet()) {
					 String key[] = entry.getKey().split("_",-1);
					
					 if(goodsSku.getSku().equals(key[0]) && 
					    (itemPre.getBatchCode() == null ? "" : itemPre.getBatchCode()).equals(key[1]) &&
					    (itemPre.getProductDate() == null ? "" : itemPre.getProductDate()).equals(key[2]) &&
					    (itemPre.getExpireDate() == null ? "" : itemPre.getExpireDate()).equals(key[3])){
						 Map<String,Integer> value = entry.getValue();
						 for (Map.Entry<String,Integer> entryV : value.entrySet()) {
							 Integer num = entryV.getValue();
							 if(inventoryType.equals(entryV.getKey())){
								EntryOrderItemConfirm item = new EntryOrderItemConfirm();
								item.setOrderLineNo(itemPre.getLineNo());
								item.setItemCode(goodsSku.getBar());
								item.setItemId(goodsSku.getId().toString());
								
								item.setInventoryType(entryV.getKey());
								item.setQuantity(itemPre.getGoodsNum());
								if(itemPre.getGoodsNum()>=num){
									item.setActualQty(num);
								}else {
									item.setActualQty(itemPre.getGoodsNum());
								}
								entryV.setValue(num-item.getActualQty());
								
								item.setBatchCode(itemPre.getBatchCode());
								item.setProductDate(itemPre.getProductDate());
								item.setExpireDate(itemPre.getExpireDate());
								item.setProduceCode(itemPre.getProduceCode());
								entryOrderItems.add(item);
							 }else {
								EntryOrderItemConfirm item = new EntryOrderItemConfirm();
								item.setOrderLineNo(itemPre.getLineNo());
								item.setItemCode(goodsSku.getBar());
								item.setItemId(goodsSku.getId().toString());
								
								item.setInventoryType(entryV.getKey());
								item.setQuantity(itemPre.getGoodsNum());
								if(itemPre.getGoodsNum()>=num){
									item.setActualQty(num);
								}else {
									item.setActualQty(itemPre.getGoodsNum());
								}
								item.setActualQty(num);
								
								item.setBatchCode(itemPre.getBatchCode());
								item.setProductDate(itemPre.getProductDate());
								item.setExpireDate(itemPre.getExpireDate());
								item.setProduceCode(itemPre.getProduceCode());
								entryOrderItems.add(item);
							 }
						 }
						break;
					 }
				}
			}
			
			//把EntryOrderConfirm和EntryOrderItemConfirm放到InstorageBillCreateConfirm
			createConfirm.setEntryOrder(entryOrder);
			createConfirm.setItem(entryOrderItems);
			
			//转成XML返回
			StringWriter writer = new StringWriter();
			JAXB.marshal(createConfirm,writer);
			logger.info(billCode+"普通入库确认成功" + writer.toString());
			return writer.toString();
		}
	}
}
